/**
 * file-list.js - 文件导览页面逻辑
 * 功能：面包屑导航、文件夹/文件列表展示、目录切换
 */

// ==================== 全局状态管理 ====================
const FileListApp = {
    // 当前路径
    currentPath: '',

    // 当前搜索关键词
    currentSearchKeyword: '',

    // 路径历史栈（用于面包屑导航）
    pathStack: [],

    // DOM 元素引用
    elements: {
        breadcrumb: null,
        fileTableBody: null,
        statusMsg: null,
        searchInput: null,
        searchBtn: null,
        uploadBtn: null,
        uploadModal: null,
        uploadModalClose: null,
        subDirectory: null,
        fileInput: null,
        confirmUploadBtn: null,
        cancelUploadBtn: null,
        uploadStatus: null,
        viewJsonModal: null,
        viewJsonModalClose: null,
        jsonFileName: null,
        jsonContent: null,
        viewJsonStatus: null,
        closeJsonViewBtn: null,
        formatJsonBtn: null,
        formatBtnIcon: null,
        formatBtnText: null,
        jsonInfo: null,
        copyJsonBtn: null,
        jsonSearchInput: null,
        jsonSearchBtn: null,
        jsonSearchNav: null,
        searchCount: null,
        searchPrevBtn: null,
        searchNextBtn: null,
        searchClearBtn: null,
        toastContainer: null
    },

    // JSON查看器状态
    jsonViewerState: {
        rawContent: '',      // 原始内容
        parsedJson: null,    // 解析后的JSON对象
        isFormatted: true,   // 默认格式化状态改为true
        currentFile: null,   // 当前文件信息
        searchKeyword: '',   // 当前搜索关键词
        searchMatches: [],   // 搜索匹配位置数组
        currentMatchIndex: -1 // 当前匹配索引
    },

    /**
     * 初始化应用
     */
    init() {
        // 获取 DOM 元素引用
        this.elements.breadcrumb = document.getElementById('breadcrumb');
        this.elements.fileTableBody = document.getElementById('fileTableBody');
        this.elements.statusMsg = document.getElementById('statusMsg');
        this.elements.searchInput = document.getElementById('searchInput');
        this.elements.searchBtn = document.getElementById('searchBtn');
        this.elements.uploadBtn = document.getElementById('uploadBtn');

        // 上传模态框元素
        this.elements.uploadModal = document.getElementById('uploadModal');
        this.elements.uploadModalClose = document.getElementById('uploadModalClose');
        this.elements.subDirectory = document.getElementById('subDirectory');
        this.elements.fileInput = document.getElementById('fileInput');
        this.elements.confirmUploadBtn = document.getElementById('confirmUploadBtn');
        this.elements.cancelUploadBtn = document.getElementById('cancelUploadBtn');
        this.elements.uploadStatus = document.getElementById('uploadStatus');

        // 查看JSON模态框元素
        this.elements.viewJsonModal = document.getElementById('viewJsonModal');
        this.elements.viewJsonModalClose = document.getElementById('viewJsonModalClose');
        this.elements.jsonFileName = document.getElementById('jsonFileName');
        this.elements.jsonContent = document.getElementById('jsonContent');
        this.elements.viewJsonStatus = document.getElementById('viewJsonStatus');
        this.elements.closeJsonViewBtn = document.getElementById('closeJsonViewBtn');
        this.elements.formatJsonBtn = document.getElementById('formatJsonBtn');
        this.elements.formatBtnIcon = document.getElementById('formatBtnIcon');
        this.elements.formatBtnText = document.getElementById('formatBtnText');
        this.elements.jsonInfo = document.getElementById('jsonInfo');
        this.elements.copyJsonBtn = document.getElementById('copyJsonBtn');
        this.elements.jsonSearchInput = document.getElementById('jsonSearchInput');
        this.elements.jsonSearchBtn = document.getElementById('jsonSearchBtn');
        this.elements.jsonSearchNav = document.getElementById('jsonSearchNav');
        this.elements.searchCount = document.getElementById('searchCount');
        this.elements.searchPrevBtn = document.getElementById('searchPrevBtn');
        this.elements.searchNextBtn = document.getElementById('searchNextBtn');
        this.elements.searchClearBtn = document.getElementById('searchClearBtn');
        this.elements.toastContainer = document.getElementById('toastContainer');

        // 绑定搜索按钮点击事件
        this.elements.searchBtn.addEventListener('click', () => {
            this.handleSearch(this.elements.searchInput.value);
        });

        // 绑定搜索框Enter键事件
        this.elements.searchInput.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') {
                this.handleSearch(this.elements.searchInput.value);
            }
        });

        // 绑定上传按钮点击事件
        this.elements.uploadBtn.addEventListener('click', () => {
            this.openUploadModal();
        });

        // 绑定上传模态框事件
        this.elements.uploadModalClose.addEventListener('click', () => {
            this.closeUploadModal();
        });
        this.elements.cancelUploadBtn.addEventListener('click', () => {
            this.closeUploadModal();
        });
        this.elements.confirmUploadBtn.addEventListener('click', () => {
            this.handleUpload();
        });

        // 绑定查看JSON模态框事件
        this.elements.viewJsonModalClose.addEventListener('click', () => {
            this.closeViewJsonModal();
        });
        this.elements.closeJsonViewBtn.addEventListener('click', () => {
            this.closeViewJsonModal();
        });
        this.elements.formatJsonBtn.addEventListener('click', () => {
            this.toggleJsonFormat();
        });
        this.elements.copyJsonBtn.addEventListener('click', () => {
            this.copyJsonContent();
        });

        // 绑定JSON搜索功能事件
        this.elements.jsonSearchBtn.addEventListener('click', () => {
            this.handleJsonSearch();
        });
        this.elements.jsonSearchInput.addEventListener('keydown', (e) => {
            if (e.key === 'Enter') {
                if (e.shiftKey) {
                    // Shift+Enter: 上一个
                    e.preventDefault();
                    this.searchPrevMatch();
                } else {
                    // Enter: 搜索或下一个
                    e.preventDefault();
                    if (this.jsonViewerState.searchKeyword) {
                        this.searchNextMatch();
                    } else {
                        this.handleJsonSearch();
                    }
                }
            } else if (e.key === 'Escape') {
                // ESC: 清除搜索
                e.preventDefault();
                this.clearJsonSearch();
            }
        });
        this.elements.searchPrevBtn.addEventListener('click', () => {
            this.searchPrevMatch();
        });
        this.elements.searchNextBtn.addEventListener('click', () => {
            this.searchNextMatch();
        });
        this.elements.searchClearBtn.addEventListener('click', () => {
            this.clearJsonSearch();
        });

        // 点击模态框背景关闭
        this.elements.uploadModal.addEventListener('click', (e) => {
            if (e.target === this.elements.uploadModal) {
                this.closeUploadModal();
            }
        });
        this.elements.viewJsonModal.addEventListener('click', (e) => {
            if (e.target === this.elements.viewJsonModal) {
                this.closeViewJsonModal();
            }
        });

        // 加载根目录
        this.loadDirectory('');
    },

    /**
     * 处理搜索
     * @param {string} keyword - 搜索关键词
     */
    handleSearch(keyword) {
        this.currentSearchKeyword = keyword.trim();
        this.loadDirectory(this.currentPath, this.currentSearchKeyword);
    },

    /**
     * 加载指定路径的目录内容
     * @param {string} fullPath - 完整路径，空字符串表示根目录
     * @param {string} nameFilter - 可选的搜索过滤条件
     */
    async loadDirectory(fullPath, nameFilter = '') {
        try {
            // 更新当前路径
            this.currentPath = fullPath;

            // 如果不是搜索触发的加载，清空搜索框和搜索关键词
            if (arguments.length === 1) {
                this.currentSearchKeyword = '';
                if (this.elements.searchInput) {
                    this.elements.searchInput.value = '';
                }
            }

            // 显示加载状态
            this.showLoading();

            // 调用 API 获取目录内容
            const response = await API.lazyLoadFile(fullPath, nameFilter);

            // 检查响应状态
            if (response.code === 200 && response.data) {
                // 渲染文件列表
                this.renderFileList(response.data);

                // 更新面包屑导航
                this.updateBreadcrumb(fullPath);

                // 隐藏状态消息
                this.hideStatus();
            } else {
                // 显示错误消息
                this.showError(response.message || '加载失败');
            }
        } catch (error) {
            console.error('加载目录失败:', error);
            this.showError('网络错误，请稍后重试');
        }
    },

    /**
     * 渲染文件列表到表格
     * @param {Array} fileList - 文件/文件夹节点数组
     */
    renderFileList(fileList) {
        const tbody = this.elements.fileTableBody;

        // 清空表格内容
        tbody.innerHTML = '';

        // 如果列表为空
        if (!fileList || fileList.length === 0) {
            tbody.innerHTML = `
                <tr>
                    <td colspan="5" style="text-align: center; color: #7f8c8d;">
                        当前目录为空
                    </td>
                </tr>
            `;
            return;
        }

        // 排序：文件夹在前，文件在后
        const sortedList = [...fileList].sort((a, b) => {
            if (a.directory === b.directory) {
                return a.name.localeCompare(b.name);
            }
            return a.directory ? -1 : 1;
        });

        // 渲染每个文件/文件夹节点
        sortedList.forEach(node => {
            const row = this.createFileRow(node);
            tbody.appendChild(row);
        });
    },

    /**
     * 创建单个文件/文件夹的表格行
     * @param {Object} node - 文件节点对象
     * @returns {HTMLTableRowElement} 表格行元素
     */
    createFileRow(node) {
        const row = document.createElement('tr');

        // 文件夹行添加可点击样式
        if (node.directory) {
            row.style.cursor = 'pointer';
            row.classList.add('folder-row');

            // 点击文件夹时加载其内容
            row.addEventListener('click', () => {
                this.loadDirectory(node.fullPath);
            });

            // 鼠标悬停效果
            row.addEventListener('mouseenter', () => {
                row.style.backgroundColor = '#f0f8ff';
            });
            row.addEventListener('mouseleave', () => {
                row.style.backgroundColor = '';
            });
        } else if (node.extension && node.extension.toLowerCase() === 'json') {
            // JSON文件添加可点击查看样式
            row.style.cursor = 'pointer';
            row.classList.add('json-file-row');

            // 点击JSON文件时查看内容
            row.addEventListener('click', () => {
                this.viewJsonFile(node);
            });

            // 鼠标悬停效果
            row.addEventListener('mouseenter', () => {
                row.style.backgroundColor = '#f0fff0';
            });
            row.addEventListener('mouseleave', () => {
                row.style.backgroundColor = '';
            });
        }

        // 类型列（图标）
        const typeCell = document.createElement('td');
        typeCell.style.textAlign = 'center';
        typeCell.style.fontSize = '1.5em';
        typeCell.textContent = node.directory ? '📁' : '📄';
        row.appendChild(typeCell);

        // 名称列
        const nameCell = document.createElement('td');
        nameCell.textContent = node.name;
        if (node.directory) {
            nameCell.style.fontWeight = '600';
            nameCell.style.color = '#3498db';
        } else if (node.extension && node.extension.toLowerCase() === 'json') {
            nameCell.style.color = '#313231';
            nameCell.style.fontWeight = '500';
        }
        row.appendChild(nameCell);

        // 大小列
        const sizeCell = document.createElement('td');
        sizeCell.textContent = node.directory ? '-' : (node.formattedSize || this.formatFileSize(node.size));
        sizeCell.style.color = '#7f8c8d';
        row.appendChild(sizeCell);

        // 修改时间列
        const timeCell = document.createElement('td');
        timeCell.textContent = node.lastModified ?
            this.formatDate(node.lastModified) : '-';
        timeCell.style.color = '#7f8c8d';
        timeCell.style.fontSize = '0.9em';
        row.appendChild(timeCell);

        // 扩展名列
        const extCell = document.createElement('td');
        extCell.textContent = node.extension || '-';
        extCell.style.color = '#95a5a6';
        extCell.style.fontSize = '0.9em';
        row.appendChild(extCell);

        return row;
    },

    /**
     * 更新面包屑导航
     * @param {string} fullPath - 当前完整路径
     */
    updateBreadcrumb(fullPath) {
        const breadcrumb = this.elements.breadcrumb;

        // 清空面包屑
        breadcrumb.innerHTML = '';

        // 根目录项（始终可点击）
        const isAtRoot = !fullPath || fullPath === '';
        const rootItem = this.createBreadcrumbItem('根目录', '', isAtRoot);
        breadcrumb.appendChild(rootItem);

        // 如果不是根目录，解析路径并创建面包屑项
        if (fullPath) {
            const pathParts = fullPath.split('/').filter(part => part.length > 0);
            let cumulativePath = '';

            pathParts.forEach((part, index) => {
                // 构建累积路径
                cumulativePath += (cumulativePath ? '/' : '') + part;

                // 添加分隔符
                const separator = document.createElement('span');
                separator.className = 'breadcrumb-separator';
                separator.textContent = ' / ';
                breadcrumb.appendChild(separator);

                // 创建面包屑项
                const isLast = (index === pathParts.length - 1);
                const item = this.createBreadcrumbItem(part, cumulativePath, isLast);
                breadcrumb.appendChild(item);
            });
        }
    },

    /**
     * 创建面包屑导航项
     * @param {string} text - 显示文本
     * @param {string} path - 对应路径
     * @param {boolean} isActive - 是否为当前激活项
     * @returns {HTMLSpanElement} 面包屑项元素
     */
    createBreadcrumbItem(text, path, isActive) {
        const item = document.createElement('span');
        item.className = 'breadcrumb-item' + (isActive ? ' active' : '');
        item.textContent = text;
        item.dataset.path = path;

        // 非激活项可点击
        if (!isActive) {
            item.style.cursor = 'pointer';
            item.addEventListener('click', () => {
                this.loadDirectory(path);
            });
        }

        return item;
    },

    /**
     * 格式化文件大小
     * @param {number} bytes - 字节数
     * @returns {string} 格式化后的大小字符串
     */
    formatFileSize(bytes) {
        if (bytes === 0) return '0 B';
        if (!bytes) return '-';

        const units = ['B', 'KB', 'MB', 'GB', 'TB'];
        const k = 1024;
        const i = Math.floor(Math.log(bytes) / Math.log(k));

        return (bytes / Math.pow(k, i)).toFixed(2) + ' ' + units[i];
    },

    /**
     * 格式化日期时间
     * @param {string} dateStr - 日期字符串
     * @returns {string} 格式化后的日期字符串
     */
    formatDate(dateStr) {
        if (!dateStr) return '-';

        try {
            const date = new Date(dateStr);
            const year = date.getFullYear();
            const month = String(date.getMonth() + 1).padStart(2, '0');
            const day = String(date.getDate()).padStart(2, '0');
            const hours = String(date.getHours()).padStart(2, '0');
            const minutes = String(date.getMinutes()).padStart(2, '0');

            return `${year}-${month}-${day} ${hours}:${minutes}`;
        } catch (e) {
            return dateStr;
        }
    },

    /**
     * 显示加载状态
     */
    showLoading() {
        this.elements.fileTableBody.innerHTML = `
            <tr>
                <td colspan="5" style="text-align: center; color: #7f8c8d;">
                    <span class="loading">正在加载...</span>
                </td>
            </tr>
        `;
    },

    /**
     * 显示错误消息
     * @param {string} message - 错误消息文本
     */
    showError(message) {
        const statusMsg = this.elements.statusMsg;
        statusMsg.textContent = message;
        statusMsg.className = 'status error';
        statusMsg.style.display = 'block';

        // 清空文件列表
        this.elements.fileTableBody.innerHTML = `
            <tr>
                <td colspan="5" style="text-align: center; color: #e74c3c;">
                    加载失败，请重试
                </td>
            </tr>
        `;
    },

    /**
     * 隐藏状态消息
     */
    hideStatus() {
        this.elements.statusMsg.style.display = 'none';
    },

    /**
     * 打开上传文件模态框
     */
    openUploadModal() {
        // 如果当前在某个目录下，自动填充子目录输入框
        if (this.currentPath) {
            this.elements.subDirectory.value = this.currentPath;
        } else {
            this.elements.subDirectory.value = '';
        }

        // 清空文件选择和状态消息
        this.elements.fileInput.value = '';
        this.elements.uploadStatus.style.display = 'none';

        // 重置按钮状态（确保按钮可用）
        this.elements.confirmUploadBtn.disabled = false;

        // 显示模态框
        this.elements.uploadModal.style.display = 'flex';
        document.body.classList.add('modal-open');
    },

    /**
     * 关闭上传文件模态框
     */
    closeUploadModal() {
        // 隐藏模态框
        this.elements.uploadModal.style.display = 'none';
        document.body.classList.remove('modal-open');

        // 重置按钮状态（确保下次打开时按钮可用）
        this.elements.confirmUploadBtn.disabled = false;

        // 清空表单
        this.elements.fileInput.value = '';
        this.elements.uploadStatus.style.display = 'none';
    },

    /**
     * 处理文件上传
     */
    async handleUpload() {
        try {
            // 获取选中的文件
            const file = this.elements.fileInput.files[0];
            if (!file) {
                this.showUploadMessage('请选择要上传的文件', 'error');
                return;
            }

            // 验证文件类型（仅允许JSON）
            const fileName = file.name.toLowerCase();
            if (!fileName.endsWith('.json')) {
                this.showUploadMessage('只支持上传 JSON 格式的文件', 'error');
                return;
            }

            // 获取子目录路径
            let subDir = this.elements.subDirectory.value.trim();

            // 验证目录格式（如果填写了的话）
            if (subDir) {
                // 移除首尾的斜杠
                subDir = subDir.replace(/^\/+|\/+$/g, '');

                // 验证格式：只允许字母、数字、下划线、横线和斜杠
                if (!/^[a-zA-Z0-9_\-\/]+$/.test(subDir)) {
                    this.showUploadMessage('目录路径格式不正确，只能包含字母、数字、下划线、横线和斜杠', 'error');
                    return;
                }
            }

            // 显示上传中状态
            this.showUploadMessage('正在上传文件...', 'info');
            this.elements.confirmUploadBtn.disabled = true;

            // 构建FormData
            const formData = new FormData();
            formData.append('file', file);
            if (subDir) {
                formData.append('prefix', subDir);
            }

            // 调用上传API
            const response = await API.uploadFile(formData);

            // 处理响应
            if (response.code === 200) {
                this.showUploadMessage('文件上传成功！', 'success');

                // 延迟关闭模态框并刷新当前目录
                setTimeout(() => {
                    this.closeUploadModal();
                    this.loadDirectory(this.currentPath);
                }, 1500);
            } else {
                this.showUploadMessage(response.message || '上传失败', 'error');
                this.elements.confirmUploadBtn.disabled = false;
            }
        } catch (error) {
            console.error('上传文件失败:', error);
            this.showUploadMessage('网络错误，请稍后重试', 'error');
            this.elements.confirmUploadBtn.disabled = false;
        }
    },

    /**
     * 显示上传状态消息
     * @param {string} message - 消息内容
     * @param {string} type - 消息类型：'success' | 'error' | 'info'
     */
    showUploadMessage(message, type) {
        const statusEl = this.elements.uploadStatus;
        statusEl.textContent = message;
        statusEl.className = 'status ' + (type === 'error' ? 'error' : type === 'success' ? 'success' : '');
        statusEl.style.display = 'block';
    },

    /**
     * 查看JSON文件内容
     * @param {Object} node - 文件节点对象
     */
    async viewJsonFile(node) {
        try {
            // 重置状态
            this.jsonViewerState.rawContent = '';
            this.jsonViewerState.parsedJson = null;
            this.jsonViewerState.isFormatted = true; // 默认格式化
            this.jsonViewerState.currentFile = node;
            this.jsonViewerState.searchKeyword = '';
            this.jsonViewerState.searchMatches = [];
            this.jsonViewerState.currentMatchIndex = -1;

            // 设置文件名标题
            this.elements.jsonFileName.textContent = `📄 ${node.name}`;

            // 显示加载状态
            this.elements.jsonContent.innerHTML = '<span style="color: #7f8c8d;">正在加载文件内容...</span>';
            this.elements.viewJsonStatus.style.display = 'none';
            this.elements.jsonInfo.textContent = '';

            // 重置按钮状态为"原始"（因为默认显示格式化）
            this.elements.formatBtnText.textContent = '原始';
            this.elements.formatBtnIcon.textContent = '📄';
            this.elements.formatJsonBtn.disabled = true;

            // 清空搜索框
            this.elements.jsonSearchInput.value = '';
            this.elements.jsonSearchNav.style.display = 'none';

            // 打开模态框
            this.elements.viewJsonModal.style.display = 'flex';
            document.body.classList.add('modal-open');

            // 调用API获取文件流
            const response = await API.getFileStream(node.fullPath);

            if (!response.ok) {
                throw new Error('获取文件内容失败');
            }

            // 获取文件内容文本
            const text = await response.text();
            this.jsonViewerState.rawContent = text;

            // 尝试解析JSON
            try {
                const jsonData = JSON.parse(text);
                this.jsonViewerState.parsedJson = jsonData;

                // 启用格式化按钮
                this.elements.formatJsonBtn.disabled = false;

                // 默认显示格式化内容（带语法高亮）
                this.displayFormattedJson();

                // 显示文件信息
                this.updateJsonInfo(text);

            } catch (parseError) {
                // JSON解析失败，显示原始文本
                this.elements.jsonContent.textContent = text;
                this.elements.jsonContent.className = 'json-content json-error';
                this.showViewJsonMessage('文件内容不是有效的JSON格式', 'error');
                this.elements.formatJsonBtn.disabled = true;
            }
        } catch (error) {
            console.error('查看文件失败:', error);
            this.elements.jsonContent.innerHTML = '';
            this.showViewJsonMessage('无法加载文件内容，请重试', 'error');
            this.elements.formatJsonBtn.disabled = true;
        }
    },

    /**
     * 显示原始JSON（未格式化）
     */
    displayRawJson() {
        this.jsonViewerState.isFormatted = false;
        this.elements.jsonContent.textContent = this.jsonViewerState.rawContent;
        this.elements.jsonContent.className = 'json-content';
        this.elements.formatBtnText.textContent = '格式化';
        this.elements.formatBtnIcon.textContent = '✨';
    },

    /**
     * 显示格式化的JSON（带语法高亮）
     */
    displayFormattedJson() {
        this.jsonViewerState.isFormatted = true;
        const formatted = JSON.stringify(this.jsonViewerState.parsedJson, null, 2);

        // 应用语法高亮
        const highlighted = this.highlightJson(formatted);
        this.elements.jsonContent.innerHTML = highlighted;
        this.elements.jsonContent.className = 'json-content json-highlighted';

        this.elements.formatBtnText.textContent = '原始';
        this.elements.formatBtnIcon.textContent = '📄';
    },

    /**
     * 切换JSON格式化显示
     */
    toggleJsonFormat() {
        if (!this.jsonViewerState.parsedJson) {
            return;
        }

        if (this.jsonViewerState.isFormatted) {
            // 当前是格式化状态，切换到原始显示
            this.displayRawJson();
        } else {
            // 当前是原始状态，切换到格式化显示
            this.displayFormattedJson();
        }
    },

    /**
     * JSON语法高亮
     * @param {string} json - 格式化后的JSON字符串
     * @returns {string} HTML字符串
     */
    highlightJson(json) {
        // 转义HTML特殊字符
        json = json.replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');

        // 语法高亮规则
        json = json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?)/g, (match) => {
            let cls = 'json-string';
            if (/:$/.test(match)) {
                // 键名
                cls = 'json-key';
            }
            return '<span class="' + cls + '">' + match + '</span>';
        });

        // 数字
        json = json.replace(/\b(-?\d+\.?\d*)\b/g, '<span class="json-number">$1</span>');

        // 布尔值
        json = json.replace(/\b(true|false)\b/g, '<span class="json-boolean">$1</span>');

        // null
        json = json.replace(/\bnull\b/g, '<span class="json-null">null</span>');

        return json;
    },

    /**
     * 更新JSON信息显示
     * @param {string} text - JSON文本
     */
    updateJsonInfo(text) {
        const lines = text.split('\n').length;
        const size = new Blob([text]).size;
        const sizeStr = size < 1024 ? size + ' B' :
            size < 1024 * 1024 ? (size / 1024).toFixed(2) + ' KB' :
                (size / (1024 * 1024)).toFixed(2) + ' MB';

        this.elements.jsonInfo.textContent = `${lines} 行 | ${sizeStr}`;
    },

    /**
     * 复制JSON内容到剪贴板
     */
    async copyJsonContent() {
        try {
            const content = this.jsonViewerState.isFormatted
                ? JSON.stringify(this.jsonViewerState.parsedJson, null, 2)
                : this.jsonViewerState.rawContent;

            await navigator.clipboard.writeText(content);
            this.showViewJsonMessage('已复制到剪贴板', 'success');

            // 3秒后自动隐藏提示
            setTimeout(() => {
                this.elements.viewJsonStatus.style.display = 'none';
            }, 3000);
        } catch (error) {
            console.error('复制失败:', error);
            this.showViewJsonMessage('复制失败，请手动选择复制', 'error');
        }
    },

    /**
     * 显示查看JSON的状态消息
     * @param {string} message - 消息内容
     * @param {string} type - 消息类型：'success' | 'error' | 'info'
     */
    showViewJsonMessage(message, type) {
        const statusEl = this.elements.viewJsonStatus;
        statusEl.textContent = message;
        statusEl.className = 'status ' + (type === 'error' ? 'error' : type === 'success' ? 'success' : '');
        statusEl.style.display = 'block';
    },

    /**
     * 关闭查看JSON模态框
     */
    closeViewJsonModal() {
        this.elements.viewJsonModal.style.display = 'none';
        document.body.classList.remove('modal-open');
    },

    /**
     * 处理JSON搜索
     */
    handleJsonSearch() {
        const keyword = this.elements.jsonSearchInput.value.trim();

        if (!keyword) {
            this.showToast('请输入搜索关键词', 'warning');
            return;
        }

        // 获取当前显示的内容
        const content = this.elements.jsonContent.textContent || this.elements.jsonContent.innerText;

        if (!content) {
            return;
        }

        // 清除之前的搜索结果
        this.jsonViewerState.searchMatches = [];
        this.jsonViewerState.currentMatchIndex = -1;

        // 查找所有匹配项（不区分大小写）
        const lowerContent = content.toLowerCase();
        const lowerKeyword = keyword.toLowerCase();
        let index = 0;

        while ((index = lowerContent.indexOf(lowerKeyword, index)) !== -1) {
            this.jsonViewerState.searchMatches.push(index);
            index += keyword.length;
        }

        if (this.jsonViewerState.searchMatches.length === 0) {
            this.showToast(`未找到 "${keyword}"`, 'error');
            this.elements.jsonSearchNav.style.display = 'none';
            return;
        }

        // 保存搜索关键词
        this.jsonViewerState.searchKeyword = keyword;

        // 显示搜索导航
        this.elements.jsonSearchNav.style.display = 'flex';

        // 跳转到第一个匹配项
        this.jsonViewerState.currentMatchIndex = 0;
        this.highlightSearchMatches();
    },

    /**
     * 高亮显示搜索匹配项
     */
    highlightSearchMatches() {
        if (this.jsonViewerState.searchMatches.length === 0) {
            return;
        }

        // 获取纯文本内容
        const plainContent = this.jsonViewerState.isFormatted
            ? JSON.stringify(this.jsonViewerState.parsedJson, null, 2)
            : this.jsonViewerState.rawContent;

        const keyword = this.jsonViewerState.searchKeyword;

        // 从后向前插入高亮标记（避免位置偏移）
        let result = plainContent;
        const matches = [...this.jsonViewerState.searchMatches].reverse();
        const currentIndex = this.jsonViewerState.currentMatchIndex;

        matches.forEach((matchIndex, i) => {
            const reverseIndex = matches.length - 1 - i;
            const isCurrent = reverseIndex === currentIndex;
            const highlightClass = isCurrent ? 'search-match-current' : 'search-match';

            const before = result.substring(0, matchIndex);
            const match = result.substring(matchIndex, matchIndex + keyword.length);
            const after = result.substring(matchIndex + keyword.length);

            result = before + `<mark class="${highlightClass}">` + match + '</mark>' + after;
        });

        // 转义HTML特殊字符（但保留我们插入的mark标签）
        result = result.replace(/<mark class="(search-match-current|search-match)">|<\/mark>/g, (match) => {
            return '___MARK___' + match + '___MARK___';
        });

        result = result.replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');

        result = result.replace(/___MARK___&lt;mark class="(search-match-current|search-match)"&gt;___MARK___/g, (match) => {
            if (match.includes('search-match-current')) {
                return '<mark class="search-match-current">';
            }
            return '<mark class="search-match">';
        });

        result = result.replace(/___MARK___&lt;\/mark&gt;___MARK___/g, '</mark>');

        // 如果是格式化模式，应用语法高亮
        if (this.jsonViewerState.isFormatted) {
            result = this.applySyntaxHighlight(result);
        }

        // 更新显示
        this.elements.jsonContent.innerHTML = result;
        this.elements.jsonContent.className = this.jsonViewerState.isFormatted
            ? 'json-content json-highlighted'
            : 'json-content';

        // 更新计数显示
        this.updateSearchCount();

        // 滚动到当前匹配项
        this.scrollToCurrentMatch();
    },

    /**
     * 应用语法高亮（用于搜索后的内容）
     * @param {string} text - 已转义且包含mark标签的文本
     * @returns {string} 应用语法高亮后的HTML
     */
    applySyntaxHighlight(text) {
        // 保护mark标签不被语法高亮影响
        text = text.replace(/<mark class="(search-match-current|search-match)">/g, '___MARK_START_$1___');
        text = text.replace(/<\/mark>/g, '___MARK_END___');

        // 应用语法高亮
        // 字符串和键名
        text = text.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?)/g, (match) => {
            let cls = 'json-string';
            if (/:$/.test(match)) {
                cls = 'json-key';
            }
            return '<span class="' + cls + '">' + match + '</span>';
        });

        // 数字
        text = text.replace(/\b(-?\d+\.?\d*)\b/g, '<span class="json-number">$1</span>');

        // 布尔值
        text = text.replace(/\b(true|false)\b/g, '<span class="json-boolean">$1</span>');

        // null
        text = text.replace(/\bnull\b/g, '<span class="json-null">null</span>');

        // 恢复mark标签
        text = text.replace(/___MARK_START_(search-match-current|search-match)___/g, '<mark class="$1">');
        text = text.replace(/___MARK_END___/g, '</mark>');

        return text;
    },

    /**
     * 更新搜索计数显示
     */
    updateSearchCount() {
        const current = this.jsonViewerState.currentMatchIndex + 1;
        const total = this.jsonViewerState.searchMatches.length;
        this.elements.searchCount.textContent = `${current}/${total}`;
    },

    /**
     * 滚动到当前匹配项
     */
    scrollToCurrentMatch() {
        const currentMark = this.elements.jsonContent.querySelector('.search-match-current');
        if (currentMark) {
            currentMark.scrollIntoView({
                behavior: 'smooth',
                block: 'center'
            });
        }
    },

    /**
     * 跳转到下一个匹配项
     */
    searchNextMatch() {
        if (this.jsonViewerState.searchMatches.length === 0) {
            return;
        }

        // 循环到下一个
        this.jsonViewerState.currentMatchIndex =
            (this.jsonViewerState.currentMatchIndex + 1) % this.jsonViewerState.searchMatches.length;

        this.highlightSearchMatches();
    },

    /**
     * 跳转到上一个匹配项
     */
    searchPrevMatch() {
        if (this.jsonViewerState.searchMatches.length === 0) {
            return;
        }

        // 循环到上一个
        this.jsonViewerState.currentMatchIndex =
            (this.jsonViewerState.currentMatchIndex - 1 + this.jsonViewerState.searchMatches.length)
            % this.jsonViewerState.searchMatches.length;

        this.highlightSearchMatches();
    },

    /**
     * 清除JSON搜索
     */
    clearJsonSearch() {
        // 清空搜索框
        this.elements.jsonSearchInput.value = '';

        // 隐藏搜索导航
        this.elements.jsonSearchNav.style.display = 'none';

        // 重置搜索状态
        this.jsonViewerState.searchKeyword = '';
        this.jsonViewerState.searchMatches = [];
        this.jsonViewerState.currentMatchIndex = -1;

        // 重新显示内容（不带搜索高亮）
        if (this.jsonViewerState.parsedJson) {
            if (this.jsonViewerState.isFormatted) {
                this.displayFormattedJson();
            } else {
                this.displayRawJson();
            }
        }

        // 隐藏状态消息
        this.elements.viewJsonStatus.style.display = 'none';
    },

    /**
     * 显示Toast提示
     * @param {string} message - 提示消息
     * @param {string} type - 类型：'success' | 'error' | 'warning' | 'info'
     * @param {number} duration - 持续时间（毫秒），默认5000
     */
    showToast(message, type = 'info', duration = 5000) {
        // 创建toast元素
        const toast = document.createElement('div');
        toast.className = `toast toast-${type}`;

        // 设置图标
        const icons = {
            success: '✓',
            error: '✕',
            warning: '⚠',
            info: 'ℹ'
        };

        // 构建toast HTML
        toast.innerHTML = `
            <div class="toast-content">
                <span class="toast-icon">${icons[type] || icons.info}</span>
                <span class="toast-message">${message}</span>
            </div>
            <button class="toast-close" type="button">×</button>
        `;

        // 添加到容器
        this.elements.toastContainer.appendChild(toast);

        // 绑定关闭按钮事件
        const closeBtn = toast.querySelector('.toast-close');
        closeBtn.addEventListener('click', () => {
            this.removeToast(toast);
        });

        // 自动关闭
        setTimeout(() => {
            this.removeToast(toast);
        }, duration);
    },

    /**
     * 移除Toast
     * @param {HTMLElement} toast - Toast元素
     */
    removeToast(toast) {
        if (!toast || !toast.parentElement) {
            return;
        }

        // 添加移除动画
        toast.classList.add('toast-removing');

        // 动画结束后移除元素
        setTimeout(() => {
            if (toast.parentElement) {
                toast.parentElement.removeChild(toast);
            }
        }, 300);
    }
};

// ==================== 页面加载完成后初始化 ====================
document.addEventListener('DOMContentLoaded', () => {
    FileListApp.init();
});